home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / Libraries / DCLAP 6d / dclap6d / network / ncsasock / socket.c < prev    next >
Text File  |  1996-07-05  |  42KB  |  1,717 lines

  1. /*
  2.  * BSD-style socket emulation library for the Mac
  3.  * Original author: Tom Milligan
  4.  * Current author: Charlie Reiman - creiman@ncsa.uiuc.edu
  5.  *
  6.  * This source file is placed in the public domian.
  7.  * Any resemblance to NCSA Telnet, living or dead, is purely coincidental.
  8.  *
  9.  *      National Center for Supercomputing Applications
  10.  *      152 Computing Applications Building
  11.  *      605 E. Springfield Ave.
  12.  *      Champaign, IL  61820
  13.  */
  14.  
  15. /*
  16.  *
  17.  *    The following calls are implemented
  18.  *
  19.  *        socket
  20.  *        bind
  21.  *        listen
  22.  *        accept
  23.  *        connect
  24.  *        read
  25.  *        recv
  26.  *        recvfrom
  27.  *        write
  28.  *        writev
  29.  *        send
  30.  *        sendto
  31.  *        select
  32.  *        close
  33.  *        getdtablesize
  34.  *        getsockname
  35.  *        getpeername
  36.  *        shutdown
  37.  *        fcntl(F_DUPFD)
  38.  *        fcntl(F_GETFL)
  39.  *        fcntl(F_SETFL,FNDELAY)
  40.  *        dup
  41.  *        dup2
  42.  *        ioctl(FIONBIO)
  43.  *        ioctl(FIONREAD)
  44.  *
  45.  *    Non-blocking I/O is supported. All calls which would block return
  46.  *    immediately with an 'error' indicating so. Select() may be used to
  47.  *    determine when an operation can be performed.
  48.  *
  49.  *    Ioctl(FIONBIO) or fcntl(F_SETFL,FNDELAY)  can be used to toggle or set
  50.  *  the blocking status of a socket.
  51.  *
  52.  *    In a blocking situation, accept() and read() return EWOULDBLOCK and 
  53.  *    refuse to do anything. Select() for read() to learn when a incoming 
  54.  *    connection is available. 
  55.  *
  56.  *    Connect() and write() (which shouldn't take too long anyway) start 
  57.  *    the operation and return EINPROGRESS. Select for write() to learn
  58.  *    when connect() has completed. Write() on a socket which is still
  59.  *    'inprogress' return EALREADY.
  60.  *
  61.  *
  62.  *    Socket operations are single threaded and half-duplex. Fixing this is
  63.  *    left as an execise for the reader. Shouldn't be a terrible problem
  64.  *    anyway. Read() never blocks and write() only blocks for long if there
  65.  *    is a problem.
  66.  *
  67.  *    Calls which find the socket busy will return EALREADY. These are
  68.  *    read() or write() with a connect() or write() in progress.
  69.  *
  70.  *
  71.  *    Socket options are not supported. Hence no setsockopt() and getsockopt() 
  72.  *    calls.
  73.  *
  74.  *
  75.  *  CR: I attempted to support OOB data for send and recv, but not promises are
  76.  *  made as I didn't have any immediate tests for them.
  77.  *
  78.  *
  79.  *    Readv() is not implemented.
  80.  *
  81.  *
  82.  *    All calls which encounter an error will set the global variable errno
  83.  *    to indicate the problem. Some common values for errno are...
  84.  *
  85.  *        EBADF        the socket parameter is not a valid socket descriptor.
  86.  *        
  87.  *        EFAULT       a pointer parameters is rubbish.
  88.  *        
  89.  *        EINVAL       a non-pointer parameters is rubbish.
  90.  *
  91.  *        ENOTCONN     the socket should be in a connected state for this 
  92.  *                   operation, but isn't.
  93.  *
  94.  *        EISCONN      the socket is already connected.
  95.  *
  96.  * ----------------- non-blocking I/O
  97.  *
  98.  *        EWOULDBLOCK  accept() or one of the read() calls would block. 
  99.  *
  100.  *        EINPROGRESS  connect() or one of the write() operations has been 
  101.  *                   started.
  102.  *
  103.  * ----------------- SINGLE THREAD
  104.  *
  105.  *        EALREADY     an operation is already in progress on the socket.
  106.  *
  107.  * ----------------
  108.  *
  109.  *        EBUG           an internal error occured.
  110.  */
  111.  
  112. #ifdef USEDUMP
  113. # pragma load "socket.dump"
  114.  
  115. #else
  116. # include <Events.h>
  117. # include <Types.h>
  118. # include <Stdio.h>
  119.  
  120. # include <s_types.h>
  121. # include <neti_in.h>
  122. #ifdef COMP_CODEWAR
  123. #define NOWAY
  124. #undef EDOM
  125. #undef ERANGE
  126. #endif
  127. # include <neterrno.h>
  128. # include <s_file.h>
  129. # include <s_ioctl.h>
  130. # include <s_socket.h>
  131. # include <s_time.h>
  132. # include <s_uio.h>
  133.  
  134. # include "sock_str.h"
  135. # include "sock_int.h" 
  136.  
  137. #include "unixlib.h"
  138.  
  139. #endif
  140.  
  141. /* #include "sock_ext.h" */
  142.  
  143. #ifdef NOT_NOW_COMP_CODEWAR
  144. #define    EINVAL        22        /* Invalid argument */
  145. #define    EBADF        9        /* Bad file descriptor */
  146. #define    EMFILE        24        /* Too many open files */
  147. #endif
  148.  
  149. /*
  150.  *   GET YOUR GLOBALS HERE!
  151.  */
  152.  
  153. int defaultSpin(spin_msg msg,long param);
  154. SocketPtr sockets = NULL;            /* The socket table. */
  155. AllPb *pbList = NULL;                /* The pb array */
  156. short pbLast = 0;                    /* last pb used */
  157. StreamHashEntPtr streams = NULL;    /* The streams hash table */
  158. SpinFn spinroutine = (SpinFn) defaultSpin;    /* The spin routine. */ 
  159.  
  160. /*
  161.  *    s_socket(domain, type, protocol)
  162.  *
  163.  *        socket creates a MacTCP socket and returns a descriptor.
  164.  *                 
  165.  *        Domain must be AF_INET
  166.  *         
  167.  *        Type may be SOCK_STREAM to create a TCP socket or 
  168.  *        SOCK_DGRAM to create a UDP socket.
  169.  *                 
  170.  *        Protocol is ignored. (isn't it always?)
  171.  *                 
  172.  *        TCP sockets provide sequenced, reliable, two-way connection
  173.  *        based byte streams.
  174.  *
  175.  *        A TCP socket must be in a connected
  176.  *        state before any data may be sent or received on it. A 
  177.  *        connection to another socket is created with a connect() call
  178.  *        or the listen() and accept() calls.
  179.  *        Once connected, data may be transferred using read() and
  180.  *        write() calls or some variant of the send() and recv()
  181.  *        calls. When a session has been completed a close() may  be
  182.  *        performed.
  183.  *
  184.  *        
  185.  *        A UDP socket supports the exchange of datagrams (connectionless, 
  186.  *        unreliable messages of a fixed maximum length) with  
  187.  *        correspondents named in send() calls. Datagrams are
  188.  *        generally received with recv(), which returns the next
  189.  *        datagram with its return address.
  190.  *
  191.  *        An fcntl() or ioctl() call can be used to enable non-blocking I/O.
  192.  *
  193.  *        The return value is a descriptor referencing the socket or -1
  194.  *        if an error occurs, in which case global variable errno is
  195.  *        set to one of:
  196.  *
  197.  *            ENOMEM                Failed to allocate memory for the socket
  198.  *                              data structures.
  199.  *        
  200.  *            EAFNOSUPPORT         Domain wasn't AF_INET.
  201.  *
  202.  *            ESOCKTNOSUPPORT     Type wasn't SOCK_STREAM or SOCK_DGRAM.
  203.  *
  204.  *            EMFILE              The socket descriptor table is full.
  205.  */
  206. int s_socket(
  207.     Int4 domain,
  208.     Int4 type,
  209.     short protocol)
  210. {
  211.     SocketPtr sp;
  212.     int s;
  213.  
  214. #if    SOCK_DEBUG >= 3
  215.     dprintf("s_socket:\n");
  216. #endif
  217.  
  218.     sock_init();
  219.     
  220.     /*
  221.      * Support only Internet family
  222.      */
  223.     if (domain != AF_INET)
  224.         return(sock_err(EAFNOSUPPORT));
  225.         
  226.     switch(type) 
  227.     {
  228.         case SOCK_DGRAM:
  229.             protocol = IPPROTO_UDP;
  230.             break;
  231.         case SOCK_STREAM:
  232.             protocol = IPPROTO_TCP;
  233.             break;
  234.         default:
  235.             return(sock_err(ESOCKTNOSUPPORT));
  236.     }
  237.         
  238.     /*
  239.      *    Create a socket table entry 
  240.      */
  241.     s = sock_free_fd(0);        /* Get next free file descriptor */
  242.     if (s == -1)
  243.         return(sock_err(EMFILE));
  244.     sp = sockets+s;
  245.     sp->fd = s;
  246.     sp->protocol = protocol;
  247.     bzero(&sp->sa, sizeof(struct sockaddr_in));
  248.     bzero(&sp->peer, sizeof(struct sockaddr_in));
  249.     sp->sa.sin_family        = AF_INET;
  250.     sp->sa.sin_len            = sizeof(struct sockaddr_in);
  251.     sp->status                = SOCK_STATUS_USED;
  252.     sp->nonblocking            = false;
  253.  
  254.  
  255.     /* Create a new stream on the socket. */
  256.     switch(sp->protocol) 
  257.     {
  258.         case IPPROTO_UDP:
  259.             /* udp streams are not created until the last minute */
  260.             /* because we dont know if the caller wants to assign */
  261.             /* a special port number yet (via bind) and mactcp */
  262.             /* assigns udp port numbers at stream creation */
  263.             sp->sstate = SOCK_STATE_NO_STREAM;
  264.             break;
  265.  
  266.         case IPPROTO_TCP:
  267.             /* the tcp stream is created now because tcp port numbers */
  268.             /* are assigned during active/passiveOpen which is done */
  269.             /* during listen or connect */
  270.             sp->sstate = SOCK_STATE_UNCONNECTED;
  271.             if (sock_tcp_new_stream(sp) < 0)
  272.                 return(-1); /* sock_err already called */
  273.     }
  274.  
  275.     return(s);
  276. }
  277.  
  278.  
  279. /*
  280.  *    s_bind(s, name, namelen)
  281.  *
  282.  *        bind requests that the name (ip address and port) pointed to by 
  283.  *        name be assigned to the socket s.
  284.  *        
  285.  *        The return value is 0 on success or -1 if an error occurs,
  286.  *        in which case global variable errno is set to one of:
  287.  *
  288.  *        EAFNOSUPPORT        The address family in name is not AF_INET.
  289.  *        
  290.  *        EINVAL              The socket is already bound to an address.
  291.  *        
  292.  *        EADDRNOTAVAIL       The specified address is  not  available
  293.  *                             from the local machine. ie. the address
  294.  *                            portion of name was not this machine's address.
  295.  *
  296.  *        MacTCP does not separate name binding and connection establishment.
  297.  *        Therefore the port number is not verified, just stored for later use.
  298.  *
  299.  *        If a specific local port is not required, bind is optional in this
  300.  *        implementation.
  301.  */    
  302. int s_bind( 
  303.     Int4 s, 
  304.     struct sockaddr *sa_name,
  305.     Int4 namelen)
  306. {
  307.     SocketPtr sp;
  308.     struct sockaddr_in *name=(struct sockaddr_in *)sa_name;
  309.     
  310. #if    SOCK_DEBUG >= 3
  311.     dprintf("s_bind: bind %d to %08x/%d\n",
  312.         s, name->sin_addr.s_addr, name->sin_port);
  313. #endif
  314.  
  315.     if (! sock_good_fd(s))
  316.         return(sock_err(EBADF));
  317.     sp = sockets+s;
  318.         
  319.     if (namelen < sizeof(struct sockaddr_in))
  320.         return(sock_err(EINVAL));
  321.  
  322.     if (!goodptr(name)) 
  323.         return(sock_err(EFAULT));
  324.  
  325.     if (name->sin_family != AF_INET)
  326.         return(sock_err(EAFNOSUPPORT));
  327.  
  328.     if (sp->sa.sin_port != 0) /* already bound */
  329.         return(sock_err(EINVAL));
  330.  
  331.     /*
  332.      *    If client passed a local IP address, assure it is the right one
  333.      */
  334.     if (name->sin_addr.s_addr != 0) 
  335.     {
  336.         if (name->sin_addr.s_addr != xIPAddr())
  337.             return(sock_err(EADDRNOTAVAIL));
  338.     }
  339.  
  340.     /*
  341.      *    NOTE: can't check a TCP port for EADDRINUSE
  342.      *    just save the address and port away for connect or listen or...
  343.      */
  344.     sp->sa.sin_addr.s_addr = name->sin_addr.s_addr;
  345.     sp->sa.sin_port = name->sin_port;
  346.     return(0);
  347. }
  348.  
  349. /*
  350.  *    s_connect - initiate a connection on a MacTCP socket
  351.  *
  352.  *        If the parameter s is a UDP socket,
  353.  *        then  this  call specifies the address to  which  datagrams
  354.  *        are  to  be  sent, and the only address from which datagrams
  355.  *        are to be received.  
  356.  *             
  357.  *        If it is a TCP socket, then this call attempts to make a 
  358.  *        connection to another socket. The other socket is specified 
  359.  *        by an internet address and port.
  360.  *             
  361.  *        TCP sockets may successfully connect() only once;
  362.  *             
  363.  *        UDP sockets may use connect() multiple times to change
  364.  *        their association. UDP sockets may dissolve the association
  365.  *        by connecting to an invalid address, such as a null
  366.  *        address.
  367.  *        
  368.  *        If the connection or binding succeeds, then 0 is returned.
  369.  *        Otherwise a -1 is returned, and a more specific error code
  370.  *        is stored in errno.
  371.  *        
  372.  *        EAFNOSUPPORT        The address family in addr is not AF_INET.
  373.  *        
  374.  *        EHOSTUNREACH        The TCP connection came up half-way and 
  375.  *                          then failed.
  376.  *             
  377.  *    -------------- some day instead of EHOSTUNREACH -----------------
  378.  *        
  379.  *        EADDRNOTAVAIL       The specified address is not available
  380.  *                            on the remote machine.
  381.  *        
  382.  *        ETIMEDOUT           Connection establishment timed out
  383.  *                            without establishing a connection.
  384.  *        
  385.  *        ECONNREFUSED        The attempt to  connect  was  forcefully
  386.  *                            rejected.
  387.  *        
  388.  *        ENETUNREACH         The network is not reachable from here.
  389.  *        
  390.  *        EHOSTUNREACH        The host is not reachable from here.
  391.  *        
  392.  *        EADDRINUSE          The address is already in use.
  393.  */
  394. int s_connect(
  395.     Int4 s,
  396.     struct sockaddr *sa_addr,
  397.     Int4 addrlen)
  398. {
  399.     SocketPtr sp;
  400.     struct sockaddr_in *addr=(struct sockaddr_in *)sa_addr;
  401.     
  402. #if SOCK_DEBUG >= 2
  403.     dprintf("s_connect: connect %d to %08x/%d\n",
  404.         s, addr->sin_addr.s_addr, addr->sin_port);
  405. #endif
  406.     if (! sock_good_fd(s))
  407.         return(sock_err(EBADF));
  408.         
  409.     if (addrlen != sizeof(struct sockaddr_in))
  410.         return(sock_err(EINVAL));
  411.  
  412.     if (! goodptr(addr))
  413.         return(sock_err(EFAULT));
  414.  
  415.     if (addr->sin_family != AF_INET)
  416.         return(sock_err(EAFNOSUPPORT));
  417.  
  418.     sp = sockets+s;
  419.     switch(sp->protocol) 
  420.     {
  421.         case IPPROTO_UDP:
  422.             return(sock_udp_connect(sp,addr));
  423.  
  424.         case IPPROTO_TCP:
  425.             return(sock_tcp_connect(sp,addr));
  426.     }
  427.     return(0);
  428. }
  429.  
  430. /*
  431.  *    s_listen()
  432.  *
  433.  *        To accept connections, a socket is first created  with
  434.  *        socket(), a backlog for incoming connections is specified
  435.  *        with listen() and then the  connections  are  accepted  with
  436.  *        accept(). The listen() call applies only to TCP sockets.
  437.  *        
  438.  *        The qlen parameter is supposed to define the maximum length
  439.  *        the queue of pending connections may grow to. It is ignored.
  440.  *        
  441.  *        A 0 return value indicates success; -1 indicates an error.
  442.  *        
  443.  *        EOPNOTSUPP          s is not a TCP socket.
  444.  */
  445. int s_listen(
  446.     Int4 s,
  447.     Int4 qlen)
  448. {
  449. #pragma unused(qlen)
  450.     SocketPtr sp;
  451.     
  452. #if SOCK_DEBUG >= 2
  453.     dprintf("listen: listen %d\n", s);
  454. #endif
  455.     if (! sock_good_fd(s))
  456.         return(sock_err(EBADF));
  457.         
  458.     sp = sockets+s;    
  459.     switch(sp->protocol) 
  460.     {
  461.         case IPPROTO_UDP:
  462.             return(sock_err(EOPNOTSUPP));
  463.         
  464.         case IPPROTO_TCP:
  465.             return(sock_tcp_listen(sp));
  466.     }
  467.     return(0);
  468.  
  469. }
  470.  
  471. /*
  472.  *    s_accept(s, addr, addrlen)
  473.  *
  474.  *        s is a socket that has been created with socket,  bind, listen.
  475.  *        
  476.  *        Accept  extracts the  first  connection  on the queue of pending 
  477.  *        connections, creates a new socket with the same properties of s 
  478.  *        and allocates  a  new  file  descriptor,  ns, for the socket.
  479.  *        
  480.  *        If no pending connections are present on the queue, and the socket
  481.  *        is not marked as non-blocking, accept blocks the caller until
  482.  *        a connection is present. 
  483.  *        
  484.  *        If the socket is marked non-blocking  and  no pending connections 
  485.  *        are present on the queue, accept returns an error EWOULDBLOCK.
  486.  *        
  487.  *        The accepted socket, ns, is used to read and write data to and
  488.  *        from the socket which connected to this one; it is not  used
  489.  *        to  accept  more connections.  The original socket s remains
  490.  *        open for accepting further connections.
  491.  *        
  492.  *        The argument addr is a result parameter that  is  filled  in
  493.  *        with  the  address of the connecting socket. The addrlen is 
  494.  *        a value-result  parameter; it should initially contain the
  495.  *        amount of space pointed to by addr; on return it will contain 
  496.  *        the actual length (in bytes) of the address returned.
  497.  *        
  498.  *        This call is used with TCP sockets only.
  499.  *        
  500.  *        It is possible to select a socket  for  the  purposes  of
  501.  *        doing an accept by selecting it for read.
  502.  *
  503.  *        Translation: To check and see if there is a connection pending,
  504.  *        call s_select and check for pending reads.
  505.  *        
  506.  *        The call returns -1 on error.  If it succeeds, it returns  a
  507.  *        non-negative  integer  that is a descriptor for the accepted
  508.  *        socket.
  509.  *        
  510.  *        EOPNOTSUPP          s is not a TCP socket.
  511.  *        
  512.  *        EMFILE              The socket descriptor table is full.
  513.  */
  514. int s_accept(
  515.     Int4 s,
  516.     struct sockaddr *sa_addr,
  517.     Int4 *addrlen)
  518. {
  519.     SocketPtr sp;
  520.     struct sockaddr_in *addr=(struct sockaddr_in *)sa_addr;
  521.  
  522. #if SOCK_DEBUG >= 2
  523.     dprintf("s_accept: %d\n", s);
  524. #endif
  525.     if (! sock_good_fd(s))
  526.         return(sock_err(EBADF));
  527.         
  528.     if (!goodptr(addr) || !goodptr(addrlen)) 
  529.         return(sock_err(EFAULT));
  530.  
  531.     if (*addrlen < 0) 
  532.         return(sock_err(EINVAL));
  533.  
  534.     if (sock_free_fd(0) == -1)
  535.         return(sock_err(EMFILE));
  536.  
  537.     sp = sockets+s;
  538.     switch(sp->protocol) 
  539.     {
  540.         case IPPROTO_UDP:
  541.             return(sock_err(EOPNOTSUPP));
  542.         case IPPROTO_TCP:
  543.             return(sock_tcp_accept(sp,addr,addrlen));
  544.     }
  545.     return(sock_err(EFAULT));
  546. }
  547.  
  548. /*
  549.  * s_accept_once
  550.  *
  551.  * A mac specific routine, designed to compenstate for a bug
  552.  * in MacTCP. If you close a passive, unconnected stream,
  553.  * MacTCP will generate an error. s_accept always creates
  554.  * a new listening (passive open) stream that will eventually
  555.  * need to be closed. s_accept_once does not create a new
  556.  * listening socket. It will return the same socket originally
  557.  * passed to it, and NO more connections will be accepted
  558.  * on the old listening port.
  559.  *
  560.  * Other than that, it is identical to s_accept.
  561.  */
  562. int s_accept_once(
  563.     Int4 s,
  564.     struct sockaddr *sa_addr,
  565.     Int4 *addrlen)
  566. {
  567.     SocketPtr sp;
  568.     struct sockaddr_in *addr=(struct sockaddr_in *)sa_addr;
  569.  
  570. #if SOCK_DEBUG >= 2
  571.     dprintf("s_accept: %d\n", s);
  572. #endif
  573.     if (! sock_good_fd(s))
  574.         return(sock_err(EBADF));
  575.         
  576.     if (!goodptr(addr) || !goodptr(addrlen)) 
  577.         return(sock_err(EFAULT));
  578.  
  579.     if (*addrlen < 0) 
  580.         return(sock_err(EINVAL));
  581.  
  582.     if (sock_free_fd(0) == -1)
  583.         return(sock_err(EMFILE));
  584.  
  585.     sp = sockets+s;
  586.     switch(sp->protocol) 
  587.     {
  588.         case IPPROTO_UDP:
  589.             return(sock_err(EOPNOTSUPP));
  590.         case IPPROTO_TCP:
  591.             {
  592.             int        returnCode;
  593.             
  594.             returnCode=sock_tcp_accept_once(sp,addr,addrlen);
  595.             return (returnCode ? returnCode : s );
  596.             }
  597.     }
  598.     return(sock_err(EFAULT));
  599. }
  600.  
  601. /*
  602.  *    s_close(s)
  603.  *
  604.  *        The close call destroys the socket s. If this is the last reference 
  605.  *        to the underlying MacTCP stream, then the stream will be released.
  606.  *    
  607.  *        A 0 return value indicates success; -1 indicates an error.
  608.  *
  609.  *        NOTE: if non-blocking I/O is enabled EWOULDBLOCK will be returned
  610.  *            if there are TCP writes in progress. (UDP writes are
  611.  *            performed synchronously.)
  612.  *
  613.  *              All reads are terminated and unread data is lost.
  614.  */
  615. int s_close(
  616.     Int4 s)
  617. {
  618.     int t;
  619.     SocketPtr sp;
  620.     int status;
  621.     
  622. #if SOCK_DEBUG >= 2
  623.     dprintf("s_close: %d\n", s);
  624. #endif
  625.     if (! sock_good_fd(s))
  626.         return(sock_err(EBADF));
  627.         
  628.     sp = sockets+s;
  629.  
  630.     /*
  631.      *    Look for duplicates of the socket.  Only close down the connection
  632.      *    if there are no duplicates(i.e. socket not dup'd).
  633.      */
  634.      for (t = 0; t < NUM_SOCKETS; t++) 
  635.      {
  636.          if (t == s)
  637.             continue;
  638.          if (!(sockets[t].status & SOCK_STATUS_USED))
  639.             continue;
  640.         else if (sockets[t].protocol == sp->protocol && sockets[t].stream == sp->stream )
  641.         {    /* found a duplicate */
  642. #if SOCK_DEBUG >= 3
  643.             dprintf("s_close: found a dup at %d(%d, don't close stream\n",
  644.                 t, sockets[t].protocol);
  645. #endif
  646.             sock_clear_fd(s);
  647.             return(0);
  648.         }
  649.     }
  650.  
  651.     /*
  652.      *    No duplicates, close the stream. 
  653.      */
  654.     switch(sp->protocol) 
  655.     {
  656.         case IPPROTO_UDP:
  657.             status = sock_udp_close(sp);
  658.             break;
  659.             
  660.         case IPPROTO_TCP:
  661.             status = sock_tcp_close(sp);
  662.             break;
  663.     }
  664.     if (status != EWOULDBLOCK)
  665.         sock_clear_fd(s);
  666.     return(status);
  667. }
  668.  
  669.  
  670. /*
  671.  *    s_read(s, buffer, buflen)
  672.  *
  673.  *    s_recv(s, buffer, buflen, flags)
  674.  *    
  675.  *    s_recvfrom(s, buffer, buflen, flags, from, fromlen)
  676.  *    
  677.  *        read() attempts to read nbytes of data from the socket s.  
  678.  *        
  679.  *        recv() and recvfrom() attempt to receive a message (ie a datagram) 
  680.  *        on the socket s. 
  681.  *
  682.  *        from returns the address of the socket which sent the message.
  683.  *        fromlen is the usual value-result length parameter. 
  684.  *        
  685.  *        Typically, read() is used with a TCP stream and recv() with
  686.  *        UDP where the idea of a message makes more sense. But in fact,
  687.  *        read() and recv() are equivalent.
  688.  *        
  689.  *        For UDP...
  690.  *            If a message (ie. datagram) is too long to fit in the supplied 
  691.  *            buffer, excess bytes will be discarded..
  692.  *
  693.  *            If no messages are available at the socket, the receive call
  694.  *            waits for a message to arrive, unless the socket is non-
  695.  *            blocking in which case -1 is returned with errno set to 
  696.  *            EWOULDBLOCK.
  697.  *
  698.  *        For TCP...
  699.  *            Regardless of non-blocking status, if less data is available
  700.  *            than has been requested, only that much data is returned.
  701.  *
  702.  *            If the socket is marked for non-blocking I/O, and the socket 
  703.  *            is empty, the operation will fail with the error EWOULDBLOCK.
  704.  *            Otherwise, the operation will block until data is available 
  705.  *            or an error occurs.
  706.  *
  707.  *            A return value of zero indicates that the stream has been
  708.  *            closed and all data has already been read. ie. end-of-file.
  709.  *        
  710.  *        Flags is ignored.
  711.  *        
  712.  *        If successful, the number of bytes actually received is
  713.  *        returned. Otherwise, a -1 is returned and the global variable
  714.  *        errno is set to indicate the error. 
  715.  *        
  716.  *        ESHUTDOWN    The socket has been shutdown for receive operations.
  717.  */
  718.  
  719. int s_recvfrom(Int4 s, void *buffer, Int4 buflen, Int4 flags, 
  720.                 struct sockaddr *sa_from, Int4 *fromlen);
  721.  
  722.  
  723. int s_read(
  724.     Int4 s,
  725.     void *buffer,
  726.     Int4 buflen)
  727. {
  728.     Int4 fromlen = 0;
  729.     return(s_recvfrom(s, buffer, buflen, 0, NULL, &fromlen));
  730. }
  731.  
  732. int s_recv(
  733.     Int4 s,
  734.     void *buffer,
  735.     Int4 buflen,
  736.     Int4 flags)
  737. {
  738.     Int4 fromlen = 0;
  739.     return(s_recvfrom(s, buffer, buflen, flags, NULL, &fromlen));
  740. }
  741.  
  742. int s_recvfrom(
  743.     Int4 s,
  744.     void *buffer,
  745.     Int4 buflen,
  746.     Int4 flags,
  747.     struct sockaddr *sa_from,
  748.     Int4 *fromlen)
  749. {
  750.     SocketPtr sp;
  751.     struct sockaddr_in *from=(struct sockaddr_in *)sa_from;
  752.  
  753. #if SOCK_DEBUG >= 3
  754.     dprintf ("s_recvfrom: %d\n", s);
  755. #endif
  756.     if (s < 0 || s >= NUM_SOCKETS)
  757.         return (sock_err (EBADF));
  758.         
  759.     sp = sockets+s;
  760.     if (! is_used (sp))
  761.         return (sock_err (EBADF));
  762.         
  763.     if (!goodptr(buffer))
  764.         return (sock_err (EFAULT));
  765.         
  766.     if (buflen <= 0)
  767.         return(sock_err(EINVAL));
  768.         
  769.     if (! (from == NULL || goodptr(from)) )
  770.         return(sock_err(EFAULT));
  771.         
  772.     if (! (fromlen == NULL || goodptr(fromlen)) )
  773.         return(sock_err(EFAULT));
  774.     else
  775.         if ( *fromlen < 0 )
  776.             return(sock_err(EINVAL));
  777.  
  778.     if (sock_noread(sp))
  779.         return(sock_err(ESHUTDOWN));
  780.  
  781.     switch(sp->protocol) 
  782.     {
  783.         case IPPROTO_UDP:
  784.             return(sock_udp_recv(sp,(char*) buffer, buflen, flags, from, (int *)fromlen));
  785.  
  786.         case IPPROTO_TCP:
  787.             return(sock_tcp_recv(sp,(char*)  buffer, buflen, flags));
  788.     }
  789.     return(sock_err(EFAULT));
  790. }
  791.  
  792.  
  793. /*
  794.  *    s_write(s, buffer, buflen)
  795.  *
  796.  *    s_writev(s, iov, iovcnt)
  797.  *
  798.  *    s_send(s, buffer, buflen, flags)
  799.  *
  800.  *    s_sendto(s, buffer, buflen, flags, to, tolen)
  801.  *
  802.  *        write() attempts to write nbytes of data to the socket s from
  803.  *        the buffer pointed to by buffer.
  804.  *        
  805.  *        writev() gathers the output data from the buffers specified 
  806.  *        by the members of the iov array. Each iovec entry specifies 
  807.  *        the base address and length of an area in memory from which 
  808.  *        data should be written.
  809.  *        
  810.  *        send() and sendto() are used to transmit a message to another 
  811.  *        socket on the socket s.
  812.  *
  813.  *        Typically, write() is used with a TCP stream and send() with
  814.  *        UDP where the idea of a message makes more sense. But in fact,
  815.  *        write() and send() are equivalent.
  816.  *        
  817.  *        For UDP...
  818.  *
  819.  *          Write() and send() operations are completed as soon as the
  820.  *          data is placed on the transmission queue.???????
  821.  *
  822.  *            The address of the target is given by to.
  823.  *
  824.  *            The message must be short enough to fit into one datagram.
  825.  *        
  826.  *            Buffer space must be available to hold the message to be 
  827.  *            transmitted, regardless of its non-blocking I/O state.
  828.  *        
  829.  *        For TCP...
  830.  *            Write() and send() operations are not considered complete
  831.  *            until all data has been sent and acknowledged.
  832.  *
  833.  *            If a socket is marked for non-blocking I/O, the operation
  834.  *            will return an 'error' of EINPROGRESS.
  835.  *        
  836.  *            If the socket is not marked for non-blocking I/O, the write will
  837.  *            block until space becomes available.
  838.  *        
  839.  *        write() and send() may be used only when the socket is in a connected
  840.  *        state, sendto() may be used at any time.
  841.  *
  842.  *        Flags is ignored.
  843.  *        
  844.  *        These calls return the number of bytes sent, or -1 if an error 
  845.  *        occurred.
  846.  *        
  847.  *        EINVAL           The sum of the iov_len values in the iov array was
  848.  *                         greater than 65535 (TCP) or 65507 (UDP) or there
  849.  *                       were too many entries in the array (16 for TCP or
  850.  *                       6 for UDP).
  851.  *
  852.  *        ESHUTDOWN        The socket has been shutdown for send operations.
  853.  *        
  854.  *        EMSGSIZE         The message is too big to send in one datagram. (UDP)
  855.  *
  856.  *        ENOBUFS          The transmit queue is full. (UDP)
  857.  */
  858.  
  859.  
  860. int s_really_send(
  861.     Int4 s,
  862.     void *buffer,
  863.     Int4 count,
  864.     Int4 flags,
  865.     struct sockaddr_in *to);
  866.     
  867.     
  868. int s_write(
  869.     Int4 s,
  870.     void *buffer,
  871.     Int4 buflen)
  872. {
  873.     return(s_really_send(s, buffer, buflen, 0, NULL));
  874.  
  875. int s_writev(
  876.     Int4 s,
  877.     struct iovec *iov,
  878.     Int4 count)
  879. {    
  880.     int        result,tally=0;
  881.     
  882.     while (count--)
  883.         {
  884.         if ( !goodptr( iov ) )
  885.             return sock_err(EFAULT);
  886.         result= s_really_send(s, (char *)(iov->iov_base),
  887.                 (int)(iov->iov_len), 0, NULL);
  888.         if (result < 0)
  889.             return sock_err(result);
  890.         iov++;
  891.         tally+=result;
  892.         }
  893.     return tally;
  894.  
  895. int s_send(
  896.     Int4 s,
  897.     void *buffer,
  898.     Int4 buflen,
  899.     Int4 flags)
  900. {
  901.     return(s_really_send(s, buffer, buflen, flags, NULL));
  902.  
  903. int s_sendto (
  904.     Int4 s,
  905.     void *buffer,
  906.     Int4 buflen,
  907.     Int4 flags,
  908.     struct sockaddr *sa_to,
  909.     Int4 tolen)
  910. {
  911.     SocketPtr sp;
  912.     struct sockaddr_in *to=(struct sockaddr_in *)sa_to;
  913.  
  914.     if (s < 0 || s >= NUM_SOCKETS)
  915.         return (sock_err (EBADF));
  916.         
  917.     sp = sockets+s;
  918.     
  919.     if (! is_used (sp))
  920.         return (sock_err (EBADF));
  921.         
  922.     if (!goodptr(buffer))
  923.         return (sock_err (EFAULT));
  924.         
  925.     if (buflen <= 0)
  926.         return(sock_err(EINVAL));
  927.         
  928.     if (to != NULL && !goodptr(to))
  929.         return(sock_err(EFAULT));
  930.         
  931.     if (to != NULL && tolen < sizeof(struct sockaddr_in))
  932.         return(sock_err(EINVAL));
  933.  
  934.     return(s_really_send(s, buffer, buflen, flags, to));
  935. }
  936.  
  937. int s_sendmsg(Int4 s,struct msghdr *msg,Int4 flags) {
  938.     SocketPtr sp;
  939.     struct iovec *iov=NULL;
  940.     int tally=0,result,count;
  941.  
  942.     if (s < 0 || s >= NUM_SOCKETS)
  943.         return (sock_err (EBADF));
  944.         
  945.     sp = sockets+s;
  946.     
  947.     if (! is_used (sp))
  948.         return (sock_err (EBADF));
  949.     if (!goodptr(msg))
  950.         return (sock_err (EFAULT));
  951.     if ( msg->msg_name != NULL && !goodptr(msg->msg_name) ) 
  952.         return (sock_err (EFAULT));
  953.     if ( msg->msg_name != NULL && msg->msg_namelen < sizeof (struct sockaddr_in))
  954.         return (sock_err (EFAULT));
  955.     
  956.     count = msg->msg_iovlen;
  957.     iov = msg->msg_iov;
  958.     while ( count -- ) {
  959.         if ( !goodptr( iov ) )
  960.             return sock_err(EFAULT);
  961.         result= s_really_send(s, (char *)(iov->iov_base),
  962.                 (int)(iov->iov_len), flags,(struct sockaddr_in *)msg->msg_name);
  963.         if (result < 0)
  964.             return (sock_err(result));
  965.         iov++;
  966.         tally+=result;
  967.         }
  968.     return tally;
  969.     }
  970.  
  971. int s_really_send(
  972.     Int4 s,
  973.     void *buffer,
  974.     Int4 count,
  975.     Int4 flags,
  976.     struct sockaddr_in *to)
  977.     
  978.     {
  979.     SocketPtr    sp;
  980.     int            tally=0;
  981.  
  982. #if SOCK_DEBUG >= 2
  983.     dprintf("s_really_send: %d  %d bytes", s, count);
  984.     if (to != NULL)
  985.         dprintf(" to %08x/%d",to->sin_addr.s_addr,to->sin_port);
  986.     dprintf("\n");
  987. #endif
  988.     if (! sock_good_fd(s))
  989.         return(sock_err(EBADF));
  990.     sp = sockets+s;
  991.  
  992. #if SOCK_DEBUG >= 2
  993.     dprintf("state %d\n",sp->sstate);
  994.     dprintf("peer %08x/%d\n",sp->peer.sin_addr.s_addr,sp->peer.sin_port);
  995. #endif
  996.     
  997.     if (sock_nowrite(sp))
  998.         return(sock_err(ESHUTDOWN));
  999.  
  1000.     switch(sp->protocol) 
  1001.         {
  1002.         case IPPROTO_UDP:
  1003.             if (to == NULL && sp->sstate != SOCK_STATE_CONNECTED) 
  1004.                 return(sock_err(ENOTCONN));
  1005.             return(sock_udp_send(sp, to,(char*)  buffer, count, flags));
  1006.             break;
  1007.             
  1008.         case IPPROTO_TCP:
  1009.             if (to != NULL) /* sendto */
  1010.                 return(sock_err(EOPNOTSUPP));
  1011.             if (sp->sstate != SOCK_STATE_CONNECTED) 
  1012.                 return(sock_err(ENOTCONN));
  1013.             return ( sock_tcp_send(sp, (char*) buffer, count,0 ));
  1014.             break;
  1015.         }
  1016.     return(sock_err(ESHUTDOWN));
  1017.     }
  1018.  
  1019.  
  1020. /*
  1021.  *    s_select(width, readfds, writefds, exceptfds, timeout)
  1022.  *
  1023.  *        select() examines the I/O descriptor  sets  whose  addresses
  1024.  *        are  passed  in  readfds,  writefds, and exceptfds to see if
  1025.  *        some of their descriptors are ready for reading,  ready  for
  1026.  *        writing, or have an exceptional condition pending.  width is
  1027.  *        the number of bits to be  checked  in  each  bit  mask  that
  1028.  *        represent  a file descriptor; the descriptors from 0 through
  1029.  *        width-1 in the  descriptor  sets  are  examined.   Typically
  1030.  *        width  has  the  value  returned by getdtablesize for the
  1031.  *        maximum number of file  descriptors.   On  return,  select
  1032.  *        replaces  the  given descriptor sets with subsets consisting
  1033.  *        of those descriptors that are ready for the requested opera-
  1034.  *        tion.  The total number of ready descriptors in all the sets
  1035.  *        is returned.
  1036.  *
  1037.  *        If timeout is not a NULL pointer,  it  specifies  a  maximum
  1038.  *        interval  to wait for the selection to complete.  If timeout
  1039.  *        is a NULL  pointer,  the  select  blocks  indefinitely.   To
  1040.  *        effect  a  poll,  the  timeout argument should be a non-NULL
  1041.  *        pointer, pointing to a zero-valued timeval structure.
  1042.  *
  1043.  *        Any of readfds, writefds, and exceptfds may be given as NULL
  1044.  *        pointers if no descriptors are of interest.
  1045.  *
  1046.  *        Using select to open a socket for reading is analogous  to
  1047.  *        performing an accept call.
  1048.  *
  1049.  *        select() returns the number of ready  descriptors  that  are
  1050.  *        contained  in  the  descriptor  sets,  or  -1  if  an  error
  1051.  *        occurred.  If the time limit expires then  select()  returns
  1052.  *        0.   If select() returns with an error the descriptor sets 
  1053.  *      will be unmodified.
  1054.  */
  1055. int s_select(
  1056.     Int4 width,
  1057.     fd_set *readfds,
  1058.     fd_set *writefds,
  1059.     fd_set *exceptfds,
  1060.     struct timeval *timeout)
  1061. {
  1062.     SocketPtr sp;
  1063.     long count;
  1064.     int s;
  1065.     long starttime, waittime;
  1066.     fd_set rd, wd, ed;
  1067.     int errorHappened;
  1068.  
  1069. #if SOCK_DEBUG >= 2
  1070.     dprintf("select:  socket: width %d\n",width);
  1071. #endif
  1072.     if (!goodptr(timeout) && timeout != NULL)
  1073.         return(sock_err(EFAULT));
  1074.     if (!goodptr(readfds) && readfds != NULL)
  1075.         return(sock_err(EFAULT));
  1076.     if (!goodptr(writefds) && writefds != NULL)
  1077.         return(sock_err(EFAULT));
  1078.     if (!goodptr(exceptfds) && exceptfds != NULL)
  1079.         return(sock_err(EFAULT));
  1080.         
  1081. #if SOCK_DEBUG >= 3
  1082.     dprintf("select: timeout %d sec, read %08x write %08x except %08x\n",
  1083.         (timeout ? timeout->tv_sec : 99999), 
  1084.         (readfds!=NULL ? *readfds : 0L),
  1085.         (writefds!=NULL ? *writefds : 0L),
  1086.         (exceptfds!=NULL ? *exceptfds : 0L));
  1087. #endif
  1088.  
  1089.     if (width > NUM_SOCKETS)    /* for now..xxx. */
  1090.         width = NUM_SOCKETS;
  1091.     count = 0;
  1092.     FD_ZERO(&rd);
  1093.     FD_ZERO(&wd);
  1094.     FD_ZERO(&ed);
  1095.  
  1096.     if (timeout) 
  1097.     {
  1098.         waittime = TVTOTICK(timeout->tv_sec,timeout->tv_usec);
  1099.         starttime = TickCount();
  1100.     }
  1101. #if SOCK_DEBUG >= 5
  1102.     dprintf("     starttime = %d(tics);  waittime = %d\n",starttime, waittime);
  1103. #endif
  1104.  
  1105.     do 
  1106.     {
  1107.         for (s = 0 , sp = sockets ; s < width ; ++s, ++sp) 
  1108.         {
  1109.             if (is_used(sp)) 
  1110.             {
  1111.                 errorHappened = 0;
  1112.                 
  1113.                 /* Check if there is data or connection available. */
  1114.                 if (readfds && FD_ISSET(s,readfds)) 
  1115.                 {
  1116.                         
  1117.                     switch(sp->protocol) 
  1118.                     {
  1119.                         case IPPROTO_UDP:
  1120.                             switch (sock_udp_can_recv(sp))
  1121.                             {
  1122.                                 case 1:
  1123.                                     FD_SET(s,&rd);
  1124.                                     ++count;
  1125.                                     break;
  1126.                                 case -1:
  1127.                                     errorHappened = 1;
  1128.                                     break;
  1129.                             }
  1130.                             break;
  1131.                 
  1132.                         case IPPROTO_TCP:
  1133.                     /* Must exit if stream is dead to avoid eternal lock up */
  1134.                             if (sock_tcp_can_read(sp) ) {
  1135.                                 FD_SET(s,&rd);
  1136.                                 ++count;
  1137.                                 } 
  1138.                             break;
  1139.                     }
  1140.                 }
  1141.                 if (writefds && FD_ISSET(s,writefds)) 
  1142.                 {
  1143.                     switch(sp->protocol) 
  1144.                     {
  1145.                         case IPPROTO_UDP:
  1146.                             switch (sock_udp_can_send(sp))
  1147.                             {
  1148.                                 case 1:
  1149.                                     FD_SET(s,&wd);
  1150.                                     ++count;
  1151.                                     break;
  1152.                                 case -1:
  1153.                                     errorHappened = 1;
  1154.                                     break;
  1155.                             }
  1156.                             break;
  1157.                 
  1158.                         case IPPROTO_TCP:
  1159.                             if (sock_tcp_can_write(sp))
  1160.                             {
  1161.                                 FD_SET(s,&wd);
  1162.                                 ++count;
  1163.                             }
  1164.                             break;
  1165.                     }
  1166.                 }
  1167.                 if (exceptfds && FD_ISSET(s,exceptfds)) 
  1168.                 {
  1169.                     if (errorHappened)  
  1170.                     {
  1171.                         FD_SET(s,&ed);
  1172.                         ++count;
  1173.                     }
  1174.                 }
  1175.             }
  1176.         }
  1177.         SPIN(false,SP_SELECT,0L)
  1178.     } 
  1179.     while(count == 0 &&(timeout == 0 || TickCount() - starttime < waittime));
  1180.  
  1181.     if (readfds)             
  1182.         *readfds = rd;
  1183.     if (writefds)             
  1184.         *writefds = wd;
  1185.     if (exceptfds)             
  1186.         *exceptfds = ed;
  1187. #if SOCK_DEBUG >= 5
  1188.     dprintf("     elapsed = %d(tics)  count %d, read %08x write %08x except %08x\n",
  1189.         TickCount()-starttime,count,
  1190.         (readfds!=NULL ? *readfds : 0L),
  1191.         (writefds!=NULL ? *writefds : 0L),
  1192.         (exceptfds!=NULL ? *exceptfds : 0L));
  1193. #endif
  1194.     return(count);
  1195. }
  1196.     
  1197. /*
  1198.  *    s_getdtablesize()
  1199.  *
  1200.  *        The entries in the socket descriptor table are numbered with small
  1201.  *        integers starting at 0. getdtablesize returns the size of the 
  1202.  *        descriptor table.
  1203.  */
  1204. int s_getdtablesize()
  1205. {
  1206.     return(NUM_SOCKETS);
  1207. }
  1208.  
  1209. /*
  1210.  *    s_getsockname(s, name, namelen)
  1211.  *
  1212.  *        getsockname returns the current name for the  socket s.
  1213.  *        Namelen should  be initialized to
  1214.  *        indicate the amount of space pointed to by name.  On  return
  1215.  *        it contains the actual size of the name returned (in bytes).
  1216.  *        
  1217.  *        A 0 is returned if the call succeeds, -1 if it fails.
  1218.  */
  1219.  
  1220. int s_getsockname(
  1221.     Int4 s,
  1222.     struct sockaddr *name,
  1223.     Int4 *namelen)
  1224. {
  1225. #if SOCK_DEBUG >= 3
  1226.     dprintf("GETSOCKNAME: %d\n", s);
  1227. #endif
  1228.     if (! sock_good_fd(s))
  1229.         return(sock_err(EBADF));
  1230.  
  1231.     if (! goodptr(name))
  1232.         return(sock_err(EFAULT));
  1233.         
  1234.     if (*namelen < 0)
  1235.         return(sock_err(EINVAL));
  1236.  
  1237.     sock_copy_addr(&sockets[s].sa, name, namelen);
  1238.     return(0);
  1239. }
  1240.  
  1241. /*
  1242.  *    s_getpeername(s, name, namelen)
  1243.  *
  1244.  *        getpeername returns the name of the peer connected to socket s.
  1245.  *
  1246.  *        The  int  pointed  to  by the namelen parameter
  1247.  *        should be  initialized  to  indicate  the  amount  of  space
  1248.  *        pointed  to  by name.  On return it contains the actual size
  1249.  *        of the name returned (in bytes).  The name is  truncated  if
  1250.  *        the buffer provided is too small.
  1251.  *        
  1252.  *        A 0 is returned if the call succeeds, -1 if it fails.
  1253.  */
  1254. int s_getpeername(
  1255.     Int4 s,
  1256.     struct sockaddr *name,
  1257.     Int4 *namelen)
  1258. {
  1259.     SocketPtr sp;
  1260.  
  1261. #if SOCK_DEBUG >= 2
  1262.     dprintf("getpeername: socket %d\n", s);
  1263. #endif
  1264.     if (! sock_good_fd(s))
  1265.         return(sock_err(EBADF));        
  1266.  
  1267.     sp = sockets+s;
  1268.     if (! is_used (sp))
  1269.         return (sock_err (EBADF));
  1270.  
  1271.     if (! goodptr(name))
  1272.         return(sock_err(EFAULT));
  1273.         
  1274.     if (*namelen < 0)
  1275.         return(sock_err(EINVAL));
  1276.  
  1277.     if (sp->sstate != SOCK_STATE_CONNECTED) 
  1278.         return(sock_err(ENOTCONN));
  1279.  
  1280.     sock_copy_addr(&sockets[s].peer, name, namelen);
  1281.  
  1282.     return(0);
  1283. }
  1284.  
  1285. /*
  1286.  *    s_shutdown(s, how)
  1287.  *
  1288.  *        shutdown call causes all or part of a full-duplex
  1289.  *        connection on the socket s to be shut down.  If
  1290.  *        how is 0, then further receives will be disallowed.  If  how
  1291.  *        is  1,  then further sends will be disallowed.  If how is 2,
  1292.  *        then further sends and receives will be disallowed.
  1293.  *        
  1294.  *        A 0 is returned if the call succeeds, -1 if it fails.
  1295.  */
  1296. int s_shutdown(
  1297.     Int4 s,
  1298.     Int4 how)
  1299. {
  1300.     SocketPtr sp;
  1301.     
  1302. #if SOCK_DEBUG >= 2
  1303.     dprintf("shutdown: shutdown %d\n", s);
  1304. #endif
  1305.     if (! sock_good_fd(s))
  1306.         return(sock_err(EBADF));
  1307.     sp = sockets+s;
  1308.  
  1309.     switch(how) 
  1310.     {
  1311.         case 0 : 
  1312.             sp->status |= SOCK_STATUS_NOREAD;
  1313.             break;
  1314.             
  1315.         case 1 : 
  1316.             sp->status |= SOCK_STATUS_NOWRITE;
  1317.             break;
  1318.  
  1319.         case 2 :
  1320.             sp->status |= SOCK_STATUS_NOREAD | SOCK_STATUS_NOWRITE;
  1321.             break;
  1322.             
  1323.         default :
  1324.             return(sock_err(EINVAL));
  1325.     }
  1326.     return(0);
  1327. }
  1328.  
  1329. /*
  1330.  *    fcntl() operates on the socket s according to the order in cmd:
  1331.  *
  1332.  *        F_DUPFD    Like Dup. Returns a new descriptor which refers to the 
  1333.  *                same MacTCP stream as s and has the same descriptor 
  1334.  *                status.
  1335.  *
  1336.  *        F_GETFL    returns the descriptor status flags for s. The only
  1337.  *                flag supported is FNDELAY for non-blocking i/o.
  1338.  *
  1339.  *        F_SETFL    sets descriptor status flags for s. The only
  1340.  *                 flag supported is FNDELAY for non-blocking i/o.
  1341.  *
  1342.  *        A dup or F_DUPFD operation copies the descriptor status flags
  1343.  *        maintained by F_SETFL, but once the copy is done, the two are
  1344.  *        disjoint. THIS IS DIFFERENT FROM UNIX.
  1345.  *
  1346.  *        Upon successful completion, the value  returned  depends  on
  1347.  *        cmd as follows:
  1348.  *            F_DUPFD   A new descriptor.
  1349.  *             F_GETFL   Value of flags.
  1350.  *            F_SETFL   0.
  1351.  *
  1352.  *        On error, a value of -1  is returned and errno is set to indicate 
  1353.  *        the error.
  1354.  *
  1355.  *        EBADF           s is not a valid open descriptor.
  1356.  *
  1357.  *        EMFILE          cmd is F_DUPFD and socket descriptor table is full.
  1358.  *
  1359.  *        EINVAL          cmd is F_DUPFD and arg  is  negative  or
  1360.  *                      greater   than   the  maximum  allowable
  1361.  *                      number (see getdtablesize).
  1362.  */
  1363. int s_fcntl(
  1364.     Int4 s,
  1365.     /* unsigned Int4 cmd,*/
  1366.     unsigned long cmd,
  1367.     Int4 arg)
  1368. {
  1369. #if SOCK_DEBUG >= 2
  1370.     dprintf("s_fcntl: %d\n", s);
  1371. #endif
  1372.  
  1373.     if (! sock_good_fd(s))
  1374.         return(sock_err(EBADF));
  1375.  
  1376.     switch(cmd) 
  1377.     {
  1378.         /*
  1379.          * Duplicate a socket.
  1380.          */
  1381.         case F_DUPFD : 
  1382.         {
  1383.             int s1;
  1384.             
  1385.             if (arg < 0 || arg >= NUM_SOCKETS)
  1386.                 return(sock_err(EINVAL));
  1387.             
  1388.             s1 = sock_free_fd(arg);
  1389.             if (s1 == -1)
  1390.                 return(sock_err(EMFILE));
  1391.             
  1392.             sock_dup_fd(s,s1);
  1393.             return(s1);
  1394.         }
  1395.         
  1396.         /*
  1397.          *  Get socket status.  This is like getsockopt().
  1398.          *  Only supported descriptor status is FNDELAY.
  1399.          */
  1400.         case F_GETFL : 
  1401.         {
  1402.             SocketPtr sp;
  1403.     
  1404.             sp = sockets+s;
  1405.             if (sp->nonblocking)
  1406.                 return(FNDELAY);
  1407.             else
  1408.                 return(0);
  1409.         }
  1410.         
  1411.         /*
  1412.          *  Set socket status.  This is like setsockopt().
  1413.          *  Only supported descriptor status is FNDELAY.
  1414.          */
  1415.         case F_SETFL : 
  1416.         {
  1417.             SocketPtr sp;
  1418.     
  1419.             sp = sockets+s;
  1420.             if (arg & FNDELAY)
  1421.                 sp->nonblocking = true;
  1422.             else
  1423.                 sp->nonblocking = false;
  1424.             
  1425.             return(0);
  1426.         }
  1427.     }
  1428.     return(0);
  1429. }
  1430.  
  1431. /*
  1432.  *    dup(s)
  1433.  *
  1434.  *    dup2(s, news)
  1435.  *
  1436.  *        dup() duplicates an existing socket descriptor.   The  argu-
  1437.  *        ment s is a small non-negative integer index in the per-
  1438.  *        process descriptor table.  The value must be less  than  the
  1439.  *        size  of  the  table, which is returned by getdtablesize(2).
  1440.  *        The new descriptor returned by the call is the  lowest  num-
  1441.  *        bered  descriptor  that  is not currently in use by the pro-
  1442.  *        cess.
  1443.  *
  1444.  *        In the second form  of  the  call,  the  value  of  the  new
  1445.  *        descriptor  desired  is  specified.   If  that descriptor is
  1446.  *        already in use, the descriptor is first deallocated as if  a
  1447.  *        close(2) call had been done first.
  1448.  *
  1449.  *        The value -1 is returned if an error occurs in either  call.
  1450.  *        The  external  variable  errno  indicates  the  cause of the
  1451.  *        error.
  1452.  *
  1453.  *        EBADF               s or  news is  not  a  valid  socket
  1454.  *                            descriptor.
  1455.  *
  1456.  *        EMFILE              Too many descriptors are active.
  1457.  */
  1458. int s_dup(
  1459.     Int4 s)
  1460. {
  1461.     return(s_fcntl(s, F_DUPFD, 0));
  1462. }
  1463.  
  1464. int s_dup2(
  1465.     Int4 s,
  1466.     Int4 s1)
  1467. {
  1468.     if (! sock_good_fd(s))
  1469.         return(sock_err(EBADF));
  1470.  
  1471.     if (s1 < 0 || s1 >= NUM_SOCKETS)
  1472.         return(sock_err(EBADF));
  1473.  
  1474.     if (is_used(sockets+s1))
  1475.     {
  1476.         if (s_close(s1) == -1)
  1477.             return(-1);
  1478.     }
  1479.     sock_dup_fd(s,s1);
  1480.     return(s1);
  1481. }
  1482.  
  1483.  
  1484. /*
  1485.  * s_Ioctl()
  1486.  */
  1487. int s_ioctl(
  1488.     Int4 d,
  1489.     Int4 request,
  1490.     Int4 *argp)
  1491. {
  1492.     struct    ifreq    *ifr;
  1493.     TCPiopb        *tpb;
  1494.     SocketPtr    sp;
  1495.     int            size;
  1496.  
  1497. #if SOCK_DEBUG >= 2
  1498.     dprintf("s_ioctl: %d, request %d\n", d,request);
  1499. #endif
  1500.  
  1501.     if (! sock_good_fd(d))
  1502.         return(sock_err(EBADF));
  1503.  
  1504.     sp = sockets+d;
  1505.     
  1506.     /*
  1507.      * Interpret high order word to find amount of data to be copied 
  1508.      * to/from the user's address space.
  1509.      */
  1510.     size =(request &~(IOC_INOUT | IOC_VOID)) >> 16;
  1511.     
  1512.     /*
  1513.      * Zero the buffer on the stack so the user gets back something deterministic.
  1514.      */
  1515.     if ((request & IOC_OUT) && size)
  1516.         bzero((Ptr)argp, size);
  1517.  
  1518.     ifr =(struct ifreq *)argp;
  1519.     switch(request) 
  1520.     {
  1521.         /* Non-blocking I/O */
  1522.         case FIONBIO:
  1523.             sp->nonblocking = *(Boolean *)argp;
  1524.             return(0);
  1525.  
  1526.          /* Number of bytes on input Q */
  1527.         case FIONREAD:
  1528.             tpb = (TCPiopb*)sock_fetch_pb(sp);
  1529.             sp->dataavail = xTCPBytesUnread(sp);
  1530.             *(int *)argp=sp->dataavail;
  1531.             return 0;
  1532.  
  1533. #ifdef IOCTL_LATER    
  1534.         /*
  1535.          *    Get interface list.  Pass in buffer and buffer length.
  1536.          *    Returns list of length one of ifreq's 
  1537.          */
  1538.         case SIOCGIFCONF: 
  1539.         {    
  1540.             struct ifconf *ifc =(struct ifconf *)argp;
  1541.             struct ifreq *req = ifc->ifc_req;
  1542.             int reqlen;
  1543.             struct sockaddr_in *addr;
  1544.             
  1545.             /*
  1546.              *    Fill in req fields for the IF's name and local IP addr.
  1547.              */
  1548.             strncpy(req->ifr_name, myIFName, IFNAMSIZ);
  1549.             addr =(struct sockaddr_in *)&req->ifr_addr;
  1550.             addr->sin_family         = AF_INET;
  1551.             addr->sin_addr.s_addr    = myIPAddress;
  1552.             addr->sin_port            = 0;
  1553.             bzero(addr->sin_zero, sizeof(addr->sin_zero));
  1554.             ifc->ifc_len = sizeof(*req);
  1555.                     
  1556.             return(0);            
  1557.         }
  1558.  
  1559.         /*
  1560.          *    Returns MTU of specified IF.
  1561.          */
  1562.         case SIOCGIFMTU: 
  1563.         {    
  1564.             /* don't check IF specification - we only have one anyway */
  1565.             *(int *)ifr->ifr_data= xMaxMTU();
  1566.             return(0);
  1567.         }
  1568.         
  1569.         /*
  1570.          *    Returns local IP Address of IF
  1571.          */
  1572.         case SIOCGIFADDR: 
  1573.         {
  1574.             struct sockaddr_in *addr;
  1575.             
  1576.             /* don't check IF specification - we only have one anyway */
  1577.  
  1578.             addr = &ifr->ifr_addr;
  1579.             addr->sin_addr.s_addr = xIPAddr();
  1580.             addr->sin_family = AF_INET;
  1581.             return(0);
  1582.         }
  1583.  
  1584.         case SIOCGIFDSTADDR:         /* For point to point, which we don't support */
  1585.             return(sock_err(EINVAL));
  1586.  
  1587.         case SIOCGIFFLAGS:             /* Returns IF flags(none yet) */
  1588.             ifr->ifr_flags = 0;
  1589.             return(0);
  1590.             
  1591.         /*
  1592.          *    Return broadcast address - net address plus all ones in host part
  1593.          */
  1594.         case SIOCGIFBRDADDR:     
  1595.         {
  1596.             struct sockaddr_in *addr;
  1597.             
  1598.             /* don't check IF specification */
  1599.             /* we only have one and its broadcast  */
  1600.                 
  1601.             addr = &ifr->ifr_addr;
  1602.             addr->sin_addr.s_addr = xIPAddr() | ~xNetMask();
  1603.             return(0);
  1604.         }
  1605. #endif IOCTL_LATER    
  1606.         default :
  1607.             return(sock_err(EOPNOTSUPP));
  1608.     }
  1609. }
  1610.  
  1611. /*
  1612.  *    s_setsockopt()
  1613.  *
  1614.  *        Set socket options. None implemented. In Unix there are...
  1615.  *
  1616.  *          SO_REUSEADDR        toggle local address reuse
  1617.  *          SO_KEEPALIVE        toggle keep connections alive
  1618.  *          SO_DONTROUTE        toggle routing bypass for  outgoing
  1619.  *                              messages
  1620.  *          SO_LINGER           linger on close if data present
  1621.  *          SO_BROADCAST        toggle   permission   to   transmit
  1622.  *                              broadcast messages
  1623.  *          SO_OOBINLINE        toggle  reception  of   out-of-band
  1624.  *                              data in band
  1625.  *          SO_SNDBUF           set buffer size for output
  1626.  *          SO_RCVBUF           set buffer size for input
  1627.  *          SO_TYPE             get the type  of  the  socket  (get
  1628.  *                              only)
  1629.  *          SO_ERROR            get and clear error on  the  socket
  1630.  *                             (get only)
  1631.  */
  1632. int s_setsockopt(
  1633.     Int4 s,
  1634.     Int4 level,
  1635.     Int4 optname,
  1636.     char *optval,
  1637.     Int4 optlen)
  1638. {
  1639. #pragma unused(optval)
  1640. #pragma unused(optlen)
  1641.     SocketPtr sp;
  1642.  
  1643. #if SOCK_DEBUG >= 3
  1644.     dprintf("SETSOCKOPT:  socket: %d  option: %d  \n", s,optname);
  1645. #endif
  1646.     if (! sock_good_fd(s))
  1647.         return(sock_err(EBADF));
  1648.  
  1649.     sp = sockets+s;
  1650.  
  1651.     /*
  1652.      * demultiplex to socket option handlers at other protocol levels.(None
  1653.      * supported yet).
  1654.      */
  1655.     switch(level) 
  1656.     {
  1657.         case SOL_SOCKET :         /* socket level option */
  1658.             switch(optname) 
  1659.             {
  1660.                 default :
  1661.                     return(0);
  1662.             }
  1663.             break;
  1664.         case IPPROTO_TCP:
  1665.             switch(optname)
  1666.             {
  1667.                 default:
  1668.                     return(0);
  1669.             }
  1670.             break;
  1671.         default :
  1672.             return(sock_err(ENOPROTOOPT));
  1673.     }
  1674.     return(0);
  1675. }
  1676.  
  1677.  
  1678. /*
  1679.  * s_setspin() - define a routine to be called repeatedly when
  1680.  *                 socket routines are blocked (ie. spinning)
  1681.  *
  1682.  *                 pass a NULL pointer to turn off a previously
  1683.  *                 defined spin routine.
  1684.  */
  1685. int s_setspin(
  1686.     SpinFn routine)
  1687. {
  1688.     if (routine == NULL || goodptr(routine))
  1689.         {
  1690.         spinroutine = routine;
  1691.         return(0);
  1692.         }
  1693.     else
  1694.         return(sock_err(EFAULT));
  1695. }
  1696.  
  1697. /*
  1698.  * s_getspin() - returns current spinroutine
  1699.  */
  1700. SpinFn s_getspin()
  1701.     {
  1702.     return (spinroutine);
  1703.     }
  1704.  
  1705.  
  1706. int defaultSpin(spin_msg msg,long param)
  1707.     {
  1708. #pragma unused (msg,param)
  1709.     EventRecord evrec;
  1710.     
  1711.     WaitNextEvent(0, &evrec, 1 /* ticks */, NULL);
  1712.     return 0;        /* return non-zero to exit current routine */
  1713.     }
  1714.